#define MAX_L 16
int minimum(__constant int a, __constant int b, __constant int c) {
    return a<b? (c<a?c:a): (c<b?c:b);
}

int OE_GPU(char*a, int aN, char* b, int bN) {
    int aaagt1C[MAX_L];
    int aaagt2C[MAX_L];
    int *d1 = aaagt1C;
    int *d2 = aaagt2C;
    if (aN >= MAX_L) aN=MAX_L;
    if (bN >= MAX_L) bN=MAX_L;

    for (int j=0;j<=bN;j++) d1[j]=j;

    for (int i=1;i<=aN;i++) {
        d2[0] = i;
        for (int j=1;j<=bN;j++) {
            d2[j] = minimum(d1[j  ] + 1,                        // deletion
                            d2[j-1] + 1,                        // insertion
                            d1[j-1] + ((a[i-1]==b[j-1])? 0:1)); // substitution
        }
        d1 = (d1==aaagt1C)? aaagt2C:aaagt1C; // table exchange 1<>2
        d2 = (d2==aaagt2C)? aaagt1C:aaagt2C; // table exchange 1<>2
    }

    return d1[bN];
}

int cl_strcpy_globalToLocal(char* dst, __global char* src, int src_offset) {
    int length = 0;
    while (src[length + src_offset] != 0 && length < MAX_L) {
        dst[length] = src[length + src_offset];
        ++length;
    }
    return length;
}

 // OpenCL Kernel Function for element by element vector addition
__kernel void TheKernel( __global char* dict,  __global int* result,  __global char* word,  int word_len )  {
    const int dict_len = 795875;

    // pozycja slowa (do sprawdzenia) w slowniku
    int wid = get_global_id(0);

    // numer slowa nie powinien być większy niż liczba wszystkich słów
    if (wid >= 800000 || wid >= dict_len)
        return;

    // kopiowanie słowa do pamięci lokalnej
    char slowo_ze_slownika[MAX_L];
    char word_as_ptr[MAX_L];
    int bN = cl_strcpy_globalToLocal(slowo_ze_slownika, dict, wid * MAX_L);
    int aN = cl_strcpy_globalToLocal(word_as_ptr, word, 0);

    // uruchomienie i zapisanie wyniku
    result[wid] = OE_GPU(word_as_ptr, aN, slowo_ze_slownika, bN);

    if (result[wid] < 0 ) {
        result[wid] = -8;
    }
}

